﻿// --- Copyright (c) 2010 Steven Hartgers ---
// Copyright (C) 2010 Steven Hartgers All rights are reserved.
// Author contact: fiinix00/at\gmail.com
// ------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more detail
//  
// You should have received a copy of the GNU General Public License 
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hack.Extensions;
using System.Drawing;

namespace Hack.Imageing
{
    public static class AsciiArtImage
    {
        public static double Contrast(this double d, double contrast)
        {
            return (((d - .5) * contrast) + .5).Bound(0, 1);
        }
        public static IEnumerable<int> To(this int start, int end)
        {
            var diff = end - start > 0 ? 1 : -1;
            for (var current = start; current != end; current += diff)
                yield return current;
        }
        public static IEnumerable<Color> GetPixels(this Bitmap image, Rectangle rect)
        {
            return from y in rect.Top.To(rect.Bottom)
                   from x in rect.Left.To(rect.Right)
                   select image.GetPixel(x, y);
        }
        public static IEnumerable<T> Iterate<T>(T initialValue, Func<T, bool> predicate, Func<T, T> next)
        {
            for (var current = initialValue; predicate(current); current = next(current))
                yield return current;
        }
        private static string[] _AsciiChars = { "#", "#", "@", "%", "=", "+", "*", ":", "-", ".", "&nbsp;" };
        public static string ConvertToAscii(Bitmap image, bool asHtml)
        {
            Boolean toggle = false;
            StringBuilder sb = new StringBuilder();

            for (int h = 0; h < image.Height; h++)
            {
                for (int w = 0; w < image.Width; w++)
                {
                    Color pixelColor = image.GetPixel(w, h);
                    //Average out the RGB components to find the Gray Color
                    int red = (pixelColor.R + pixelColor.G + pixelColor.B) / 3;
                    int green = (pixelColor.R + pixelColor.G + pixelColor.B) / 3;
                    int blue = (pixelColor.R + pixelColor.G + pixelColor.B) / 3;
                    Color grayColor = Color.FromArgb(red, green, blue);

                    //Use the toggle flag to minimize height-wise stretch
                    if (!toggle)
                    {
                        int index = (grayColor.R * 10) / 255;
                        sb.Append(_AsciiChars[index]);
                    }
                }
                if (!toggle)
                {
                    sb.Append("<BR>");
                    toggle = true;
                }
                else
                {
                    toggle = false;
                }
            }
            return sb.ToString();
        }
        public static Bitmap GetReSizedImage(Bitmap inputBitmap, int asciiWidth)
        {
            int asciiHeight = 0;
            //Calculate the new Height of the image from its width
            asciiHeight = (int)System.Math.Ceiling((double)inputBitmap.Height * asciiWidth / inputBitmap.Width);

            //Create a new Bitmap and define its resolution
            Bitmap result = new Bitmap(asciiWidth, asciiHeight);
            Graphics g = Graphics.FromImage((System.Drawing.Image)result);
            //The interpolation mode produces high quality images
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.DrawImage(inputBitmap, 0, 0, asciiWidth, asciiHeight);
            g.Dispose();
            return result;
        }
 

        //public static IEnumerable<int> To(this int start, int end)
        //{
        //    var diff = end - start > 0 ? 1 : -1;
        //    return Iterate(start, x => x != end, x => x + diff);
        //}
        //public System.Drawing.Image GenerateImage(string inputFilePath)
        //{
        //    var regions = from rect in options.Image.GetRectangle().GetSubRectangles(options.Width, options.Height)
        //                  group options.Image.GetLuminosity(rect) by rect.Y;
        //}
        /*
        using System;
using System.Linq;
using System.Collections.Generic;
using System.Drawing;
using System.Diagnostics;

static class Program
{
    static void Main(string[] args)
    {
        var options = CommandLineOptions.GetOptions(args);
        if (options == null)
            return;
        using (SetupConsole())
            ConvertAndDisplayImage(options);
    }

    static void ConvertAndDisplayImage(CommandLineOptions options)
    {
        var regions = from rect in options.Image.GetRectangle().GetSubRectangles(options.Width, options.Height)
                       group options.Image.GetLuminosity(rect) by rect.Y;

        var choices = Choice.GenerateChoices();

        Console.BackgroundColor = ConsoleColor.Black;
        foreach (var g in regions)
        {
            var top = Console.CursorTop;
            foreach (var choice in g.Select(d => d.Contrast(options.Contrast)).Select(d => choices.GetByPercent(d)))
            {
                Console.ForegroundColor = choice.Color;
                if (options.Display)
                    Console.Write(choice.Character);
            }
            if (top == Console.CursorTop && options.Display)
                Console.WriteLine();
        }
        if (options.Display)
            Console.WriteLine();
    }

    static ActionDisposable SetupConsole()
    {
        var originalBackgroundColor = Console.BackgroundColor;
        var originalForegroundColor = Console.ForegroundColor;
        return new ActionDisposable(() =>
            {
                Console.BackgroundColor = originalBackgroundColor;
                Console.ForegroundColor = originalForegroundColor;
            });
    }
}
         */
    }
}